//****************************************************************************
// Q3DAPI_C.h		
//
//		Copyright (c) 2005 QSound Labs Inc. 
//
// Created:     2005.08.11
//
// Description:	C interface functions for the Q3D Library
//              
//***************************************************************************/

#ifndef _Q3D_C_H_
#define _Q3D_C_H_

#ifdef __cplusplus
	#define FWD_DECLARE(item) class item
	extern "C" {
#else
	#define FWD_DECLARE(item) typedef struct item item
#endif

#ifndef Q3D_VERSION
	#define Q3D_VERSION 0x210
#endif

// GB - placed into one line for gcc 2.95
#define Q3D_DECLARE_HANDLE(name)  struct name##__ { int unused; }; 	typedef struct name##__* name

typedef int Q3D_BOOL;
typedef unsigned long Q3D_FREQ;
typedef long Q3D_COORD;
typedef unsigned long Q3D_REFCOUNT;

FWD_DECLARE( Q3D_IPlayControl );
FWD_DECLARE( Q3D_ISynthTextDisplay );
FWD_DECLARE( Q3D_IHostStorage );
FWD_DECLARE( Q3D_IEventTrigger );
FWD_DECLARE( Q3D_ISynthPerformance );
FWD_DECLARE( Q3D_IMidiControl );
FWD_DECLARE( Q3D_IPitchControl );
FWD_DECLARE( Q3D_IRateControl );
FWD_DECLARE( Q3D_ITempoControl );
FWD_DECLARE( Q3D_IVolumeControl );

typedef struct Q3D_HostBlock
{
	Q3D_IHostStorage* storage;
	long position;
	long length;
} Q3D_HostBlock;

#ifdef _MSC_VER
	#ifndef _Q3DIMP
	    #define _Q3DIMP __declspec(dllimport)
	#endif
	#define Q3D_CALLBACK __stdcall
	// same definition as WINAPI, but without having to include windows.h
	#define Q3D_API __stdcall
#else
	#ifndef _Q3DIMP
	    #define _Q3DIMP
	#endif
	#define Q3D_CALLBACK
	#define Q3D_API
#endif

/** handle for Environment3D instance */
Q3D_DECLARE_HANDLE(Q3D_Env);

/** the handle for a 3D Channel */
Q3D_DECLARE_HANDLE(Q3D_Channel);

/* ***************************** Channel ************************** */

typedef enum Q3D_ChannelMode {
	Q3D_EXTENDED = 0,
	Q3D_POSITIONAL
} Q3D_ChannelMode;

typedef enum Q3D_ERROR {
	Q3D_ERROR_NO_ERROR = 0,
	Q3D_ERROR_OUT_OF_MEMORY,
	Q3D_ERROR_INVALID_PARAMETER,
	Q3D_ERROR_NOT_IMPLEMENTED,
	Q3D_ERROR_UNKNOWN,
	Q3D_ERROR_INVALID_FORMAT,
	Q3D_ERROR_INVALID_STATE,
	Q3D_ERROR_NO_INTERFACE,
	Q3D_ERROR_TIME_PERIOD_EXCEEDED
	// ... additional codes to be determined
} Q3D_ERROR;


/** 
 * Create a 3D channel.
 * In POSITIONAL mode, only mono is valid.
 * @param mode the initial mode (EXTENDED or POSITIONAL)
 * @param sampleRate the original sample rate
 * @param channelCount 1 for mono, or 2 for stereo. 
 *        Must be 1 in POSITIONAL mode.
 * @return the channel handle, or 0 on error
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_Create(Q3D_Channel* pChannel, Q3D_ChannelMode mode, long sampleRate, int channelCount);
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_Destroy(Q3D_Channel channel);

/**
 * Same as Q3DC_Create, but with reference to Q3D_Env to use its memory management.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_CreateEx(Q3D_Env env, Q3D_Channel* pChannel, Q3D_ChannelMode mode, long sampleRate, int channelCount);

/**
 * Get the number of channels of this 3D channel.
 * This cannot be changed at runtime.
 * @return 1 for mono, or 2 for stereo
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_GetChannelCount(Q3D_Channel channel, int* pCount);

/**
 * Get the mode: EXTENDED or POSITIONAL.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_GetChannelMode(Q3D_Channel channel, Q3D_ChannelMode* pMode);

/**
 * Is the channel attached to the environment object?
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_IsAttached(Q3D_Channel channel, Q3D_BOOL* pIsAttached);

/**
 * Change the playback rate.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetFrequency(Q3D_Channel channel, Q3D_FREQ frequency);

/**
 * Get the playback rate.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_GetFrequency(Q3D_Channel channel, Q3D_FREQ* pFrequency);

/** 
 * In IsDeferredMode, SetPosition does not have any effect 
 * until Q3DE_Commmit() is called.
 * Coordinates are in meters.
 * If this Channel's mode is EXTENDED, this function
 * will not do anything.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetPosition(Q3D_Channel channel, Q3D_COORD x, Q3D_COORD y, Q3D_COORD z, int duration);
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_GetPosition(Q3D_Channel channel, Q3D_COORD* pX, Q3D_COORD* pY, Q3D_COORD* pZ);

_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetPolarPosition(Q3D_Channel channel, int azimuth, int elevation, Q3D_COORD range, int duration);
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_GetPolarPosition(Q3D_Channel channel, int* pAzimuth, int* pElevation, Q3D_COORD* pRange);


/** 
 * Enable/disable 3D processing on this channel.
 * If the 3D Channel's mode is EXTENDED, the
 * extended audio effect is switched off.
 * This setting does not affect reverb. To disable
 * reverb for this channel, set reverb gain to -infinity.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_Enable(Q3D_Channel channel, Q3D_BOOL enable);
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_IsEnabled(Q3D_Channel channel, Q3D_BOOL* pEnabled);

/**
 * The callback function. The 3D Channel calls this
 * function for each input buffer. The callback
 * function is responsible to fill the buffer
 * pointed to by buffer with sampleCount samples,
 * in 16-bit (or whatever is the sample format set in the 
 * Environment3D).
 *
 * If the 3D channel is stereo, the callback will fill the
 * buffer with interleaved audio data (LRLRLR...).
 * In stereo mode, buffer will receive sampleCount*4 bytes,
 * in mono mode sampleCount*2 bytes.
 */
typedef void (Q3D_CALLBACK *Q3DC_Callback)(Q3D_Channel channel,
                              void* pUserPtr,
                              void* pBuffer,
                              int sampleCount);

/**
 * Specify the callback function that will
 * be called for each audio buffer for
 * a 3D Channel.
 * @param userPtr this pointer will be passed
 *        to the callback
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetCallback(Q3D_Channel channel,
                      Q3DC_Callback callback,
                      void* pUserPtr);

/** 
 * Reverb feed per Channel.
 * Set to -infinitive to disable reverb for this 3D Channel.
 * @param gain gain in hundredths of dB (as in I3DL2), usually 0 or negative
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetReverbGain(Q3D_Channel channel, int gain);
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_GetReverbGain(Q3D_Channel channel, int* pGain);

/** 
 * Direct feed per Channel.
 * Useful for simulating obstructions.
 * @param gain gain in hundredths of dB (as in I3DL2), usually 0 or negative
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetDirectGain(Q3D_Channel channel, int gain);
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_GetDirectGain(Q3D_Channel channel, int* pGain);

/**
 * Specify the roll off for this channel.Rolloff controls the rate 
 * and distances at which the sound fades off as it moves further 
 * away from the listener.
 * The default is implementation dependent.
 *
 * Calling this function in EXTENDED mode will have no effect.
 *
 * @param minDistance the distance at which the sound starts to 
 *                    attenuate with distance.
 * @param maxDistance the distance beyond which the sound 
 *                    attenuates no further.
 * @param rolloffFactor the multiplier factor for attenuation 
 *                    of signal with distance. This value is
 *                    specified as a ratio. 1.0f is the 
 *                    default rolloff factor. Higher values cause 
 *                    the sound to attenuate faster and lower values
 *                    make the sound attenuate slower with distance. 
 *                    Attenuation is exponential.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetRollOff(Q3D_Channel channel, Q3D_COORD minDistance, 
		     Q3D_COORD maxDistance, int rollOffFactor);
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_GetRollOff(Q3D_Channel channel, Q3D_COORD* minDistance, 
		     Q3D_COORD* pMaxDistance, int* pRollOffFactor);

/**
 * Set the velocity of the sound source. 
 * Velocity is specified in meters per second in the X, Y and Z 
 * directions. Setting the velocity in no way affects the position of
 * the sound source, and vice versa.
 *
 * Calling this function in EXTENDED mode will have no effect.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetVelocity(Q3D_Channel channel, Q3D_COORD vx, Q3D_COORD vy, Q3D_COORD vz);
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_GetVelocity(Q3D_Channel channel, Q3D_COORD* pVx, Q3D_COORD* pVy, Q3D_COORD* pVz);


/**
 * Informs the 3D engine if this sound source is to be at coordinates 
 * relative to the listener or in absolute coordinates in 3D space. If 
 * relativeToListener is true, then the position of the sound source is 
 * always considered to be relative to the listener's position and 
 * orientation. No matter where the listener is and which direction the
 * listener is looking in, the sound appears to come from the same direction. 
 * For example, background music or any sound source that is
 * moving along with the listener, such as the noise from the listener's vehicle.
 * By default, all sound sources are positioned relative to the listener.
 *
 * Calling this function in EXTENDED mode will have no effect.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetListenerRelative(Q3D_Channel channel, Q3D_BOOL relative);
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_IsListenerRelative(Q3D_Channel channel, Q3D_BOOL* pRelative);

/**
 * Set the spread and delay for extended mode channels.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetExSpread(Q3D_Channel channel, int spread);
_Q3DIMP Q3D_ERROR Q3D_API Q3DC_SetExDelay(Q3D_Channel channel, int delay);


/* ***************************** Environment3D ************************** */

/** I3DL2 and MIDI compatible reverb types, merged into one list */
typedef enum Q3D_ReverbType {
    Q3D_NONE = 0,
    Q3D_ROOM,
    Q3D_BATHROOM,
    Q3D_CONCERTHALL,
    Q3D_CAVE,
    Q3D_ARENA,
    Q3D_FOREST,
    Q3D_CITY,
    Q3D_MOUNTAINS,
    Q3D_UNDERWATER,
	Q3D_AUDITORIUM,
	Q3D_ALLEY,
	Q3D_HALLWAY,
	Q3D_HANGAR,
	Q3D_HANGER = Q3D_HANGAR,
	Q3D_LIVINGROOM,
	Q3D_SMALLROOM,
	Q3D_MEDIUMROOM,
	Q3D_LARGEROOM,
	Q3D_MEDIUMHALL,
	Q3D_LARGEHALL,
	Q3D_PLATE,
	Q3D_GENERIC,
	Q3D_PADDEDCELL,
	Q3D_STONEROOM,
	Q3D_CARPETEDHALLWAY,
	Q3D_STONECORRIDOR,
	Q3D_QUARRY,
	Q3D_PLAIN,
	Q3D_PARKINGLOT,
	Q3D_SEWERPIPE
} Q3D_ReverbType;

typedef enum Q3D_OutputType {
	Q3D_SPEAKERS,
	Q3D_HEADPHONES
} Q3D_OutputType;

typedef enum Q3D_Geometry {
	Q3D_GEOMETRY_SPEAKER_DESKTOP,
	Q3D_GEOMETRY_SPEAKER_FRONT,
	Q3D_GEOMETRY_SPEAKER_SIDE
} Q3D_Geometry;

typedef struct Q3D_EnvOptions {
	int outputChannels;
	long outputRate;
	int outputBits;
	int maxFrameSize;
	void* heap;
	void* (Q3D_CALLBACK* HeapAlloc)(void* heap, size_t bytes);
	void* (Q3D_CALLBACK* HeapRealloc)(void* heap, void* ptr, size_t bytes);
	void (Q3D_CALLBACK* HeapFree)(void* heap, void* ptr);
} Q3D_EnvOptions;

/**
 * Create an instance of the 3D rendering and effects engine.
 *
 * @param outputChannels number of output channels for speaker algorithm
 * @param outputRate sample rate of output (e.g. 22050, 44100)
 * @param outputBits number of bits of output (currently only 16 supported)
 * @param maxFrameSize maximum number of samples that will be requested in a read
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_Create(Q3D_Env* env,
					  int outputChannels,
					  long outputRate,
					  int outputBits,
					  int maxFrameSize);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_Destroy(Q3D_Env env);

/**
 * Updated version with option for user-supplied memory management.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_CreateEx(Q3D_Env* env,
	Q3D_EnvOptions* pOptions, size_t cbOptions);

/**
 * Set the output type.
 * @param outputType selects whether headphones or speaker algorithms
 *        are to be used for the 3D effect
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetOutputType(Q3D_Env env, Q3D_OutputType outputType);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetOutputType(Q3D_Env env, Q3D_OutputType* pOutputType);

/**
 * Set the geometry of the output speakers.
 * @param geometry selects whether desktop or cell phone (front or side firing)
 *        speakers are to be used. Not applicable for headphones
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetSpeakerGeometry(Q3D_Env env, Q3D_Geometry geometry);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetSpeakerGeometry(Q3D_Env env, Q3D_Geometry* pGeometry);

/**
 * Enable/disable all 3D processing.
 * If disabled, all Channels will go through unaltered
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_Enable3D(Q3D_Env env, Q3D_BOOL enable);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_Is3DEnabled(Q3D_Env env, Q3D_BOOL* pEnabled);

/**
 * Enable/disable the reverb engine.
 * Reverb should also work when 3D audio is disabled.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_EnableReverb(Q3D_Env env, Q3D_BOOL enable);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_IsReverbEnabled(Q3D_Env env, Q3D_BOOL* pEnabled);

/** 
 * Global Reverb feed.
 * Set to -infinitive to disable reverb.
 * @param gain gain in hundredths of dB (as in I3DL2), usually 0 or negative
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetReverbGain(Q3D_Env env, int gain);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetReverbGain(Q3D_Env env, int* pGain);

/** add this Channel to the Environment */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_Attach(Q3D_Env env, Q3D_Channel channel);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_Detach(Q3D_Env env, Q3D_Channel channel);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_DetachAll(Q3D_Env env);

/** query environment resources: POSITIONAL channels only */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetMaxChannels(Q3D_Env env, int* pMaxChannels);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetAvailableChannels(Q3D_Env env, int* pAvailableChannels);

/**
 * Read a block of data from this environment instance.
 * This function will read from all attached Channels,
 * mix together and add the reverb (if enabled).
 *
 * It is required to read exactly sampleCount samples
 * from each attached Channel to ensure real-time
 * operation.
 *
 * This function must always fill the entire buffer.
 * The buffer size in bytes is (sampleCount * 16 * 2 / 8),
 * given that the general output format is 16-bit stereo.
 *
 * @param data pointer to buffer that receives the rendered data,
 *        in 16-bit, interleaved stereo
 *        (or whatever is the common sample format).
 * @param sampleCount number of samples to be rendered to data
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_Read(Q3D_Env env, void* pData, int sampleCount);

/** 
 * Select the reverb effect.
 * Choosing a new reverb will change the reverb time
 * and Q3DE_GetReverbTime will return the default 
 * time for the chosen preset.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetReverb(Q3D_Env env, Q3D_ReverbType rt);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetReverb(Q3D_Env env, Q3D_ReverbType* pReverb);

/** 
 * Set the approximate decay time of this reverb, overriding
 * this parameter of the preset. 
 * The decay time will be overriden when a new preset
 * is selected.
 *
 * @param decayTimeMs the new time that the reverb will
 *        approximately need to fade out by -60 dB from its, 
 *        initial level, in milliseconds.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetDecayTime(Q3D_Env env, int decayTimeMs);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetDecayTime(Q3D_Env env, int* pDecayTimeMs);

/**
 * Position coordinates in meters, using a right-handed coordinate system,
 * e.g. if x and y represent a position on the screen where the bottom
 * left corner of the screen, positive z points towards the listener.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetListenerPosition(Q3D_Env env, Q3D_COORD x, Q3D_COORD y, Q3D_COORD z, int duration);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetListenerPosition(Q3D_Env env, Q3D_COORD* pX, Q3D_COORD* pY, Q3D_COORD* pZ);

/** set the orientation of the listener */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetListenerOrientation(Q3D_Env env,
                                 int xat, int yat, int zat,
                                 int xup, int yup, int zup,
                                 int duration);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetListenerOrientation(Q3D_Env env,
                                 int* PXat, int* pYat, int* pZat,
                                 int* pXup, int* pYup, int* pZup);

/**
 * Set the velocity of the listener. 
 * It'll only affect the pitch of the sources, not the position. 
 * See Q3DC_SetVelocity for more information.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetListenerVelocity(Q3D_Env env, Q3D_COORD vx, Q3D_COORD vy, Q3D_COORD vz);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetListenerVelocity(Q3D_Env env, Q3D_COORD* pVx, Q3D_COORD* pVy, Q3D_COORD* pVz);

/**
 * Commit new positions, reverb gain and type,
 * of all Channels and this Environment3D instance.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_Commit(Q3D_Env env);


/**
 * If deferred commit is enabled, all positional methods
 * require a call to Q3DE_Commit to take effect.
 * If disabled, all positional methods will take effect immediately.
 * Default is immediate mode.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetDeferredCommit(Q3D_Env env, Q3D_BOOL deferred);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_IsDeferredCommit(Q3D_Env env, Q3D_BOOL* pDeferred);

/**
 * Reset internal state of the processing.  Good for when the audio has been
 * interrupted.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_Reset(Q3D_Env);

/**
 * QEffects settings.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetQSizzleEnable(Q3D_Env env, Q3D_BOOL enable);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetQSizzleFreq(Q3D_Env env, Q3D_FREQ freq);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetQRumbleEnable(Q3D_Env env, Q3D_BOOL enable);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetQRumbleFreq(Q3D_Env env, Q3D_FREQ freq);

/**
 * QSizzle and QLevel add a wet signal on top of the dry signal. The maximum wet signal that
 * can be applied to the dry signal is approximately 5dB. 
 * QSizzle/QRumble level: attenuation level in millibels, range = -9600 .. 0, default = -600 mB.
 * wet signal energy    : range = 0 .. 5 dB, default = 2.5dB, values are approximate, and depend
 *		on characteristics of dry signal.
 * Level setting vs. typical/approximate output
 * Level		wet			final (dry+wet)
 * -9600 mB		0    dB		dry
 * -1200 mB		1.25 dB		dry + 1.25 dB
 * - 600 mB		2.50 dB		dry + 2.50 dB	(default)
 * - 300 mB		3.75 dB		dry + 3.75 dB
 *     0 mB		5.00 dB		dry + 5.00 dB
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetQSizzleLevel(Q3D_Env env, int level);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetQRumbleLevel(Q3D_Env env, int level);

_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetQSizzleEnable(Q3D_Env env, Q3D_BOOL* pEnabled);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetQSizzleFreq(Q3D_Env env, Q3D_FREQ* pFreq);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetQSizzleLevel(Q3D_Env env, int* pLevel);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetQRumbleEnable(Q3D_Env env, Q3D_BOOL* pEnabled);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetQRumbleFreq(Q3D_Env env, Q3D_FREQ* pFreq);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetQRumbleLevel(Q3D_Env env, int* pLevel);

_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetEqualizerEnable(Q3D_Env env, Q3D_BOOL enable);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetEqualizerBandLevel(Q3D_Env env, int bandNumber, int level);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetEqualizerEnable(Q3D_Env env, Q3D_BOOL* pEnabled);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetNumEqualizerBands(Q3D_Env env, int* pBands);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetEqualizerBandLevel(Q3D_Env env, Q3D_FREQ band, int* pLevel);

_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetLoudnessEnable(Q3D_Env env, Q3D_BOOL* pEnabled);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetLoudnessEnable(Q3D_Env env, Q3D_BOOL enable);

/**
 * output conditioning (not part of mQfx).
 *
 * The Limiter lowers levels to avoid saturation.  Only appropriate for 32 bit
 * version.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_EnableLimiter(Q3D_Env env, Q3D_BOOL enabled);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_IsLimiterEnabled(Q3D_Env env, Q3D_BOOL* pEnabled);


typedef struct {
	long SamplesMeasured;
} Q3D_Stats;

typedef struct {
	int Clips;
	short Peak;
} Q3D_ChannelStats;

_Q3DIMP Q3D_ERROR Q3D_API Q3DE_EnableStats(Q3D_Env, unsigned short flags);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetStats(Q3D_Env,
	Q3D_Stats* stats, size_t statsSize, size_t channels, Q3D_ChannelStats* chStats, size_t chStatsSize);


//
// Types of algorithms used to map from velocity numbers to volume levels.
// Classical MIDI mapping is a square law (convex) but linear mapping leads
// to louder performances, which are generally preferable in mobile
// applications (i.e. teeny-tiny speakers).
//
typedef enum Q3D_VELOCITYMAPPING {
	Q3D_VELOCITY_CONVEX,
	Q3D_VELOCITY_LINEAR
} Q3D_VELOCITYMAPPING;

/**
 * Error codes for JSR-135 interfaces.
 */

#ifndef __JSR135ERRORCODE_DEFINED__
#define __JSR135ERRORCODE_DEFINED__

typedef enum JSR135ErrorCode {
	JSR135Error_No_Error,
	JSR135Error_Not_Implemented,
	JSR135Error_Not_Supported,
	JSR135Error_Invalid_Parameter,
	JSR135Error_Unknown
} JSR135ErrorCode;

#endif


typedef struct Q3D_SynthConfig
{
	unsigned short structSize;	// set this to sizeof(Q3D_SynthConfig) for versioning
	short channels;				// run synthesizer with this many output channels (can be different from global format)
	long sampleRate;			// run synthesizer at this sample rate (can be different from global rate)
	Q3D_BOOL use3d;				// attach synthesizer to 3d positioning effects
	short voices;				// total number of voices to be allocated to all the synths
	short waves;				// total number of waves to be allocated to all the synths (for SMAF files)
	short realTimeEvents;		// total number of real-time events to be reserved
	short voiceEvents;			// total number of temporary low-level voice events (e.g. volume & pitch) to be reserved at processing time
} Q3D_SynthConfig;

/**
 * Configure the synthesizer capabilities.  One DLS file is used for all songs.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetupSynth(Q3D_Env, const Q3D_HostBlock* dls, const Q3D_SynthConfig* config);

_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetSynthWavetable(Q3D_Env env, const Q3D_HostBlock* dls);


typedef enum Q3D_REVERB_TYPE {
	Q3D_REVERB_TYPE_MIDI,
	Q3D_REVERB_TYPE_I3DL2
} Q3D_REVERB_TYPE;

typedef enum Q3D_MIDI_ROOMTYPE {
	Q3D_MIDI_SMALLROOM = 0,
	Q3D_MIDI_MEDIUMROOM = 1,
	Q3D_MIDI_LARGEROOM = 2,
	Q3D_MIDI_MEDIUMHALL = 3,
	Q3D_MIDI_LARGEHALL = 4,
	Q3D_MIDI_PLATE = 8
} Q3D_MIDI_ROOMTYPE;

typedef enum Q3D_I3DL2_ROOMTYPE {
	Q3D_I3DL2_DEFAULT = 0,
	Q3D_I3DL2_GENERIC = 1,
	Q3D_I3DL2_PADDEDCELL = 2,
	Q3D_I3DL2_ROOM = 3,
	Q3D_I3DL2_BATHROOM = 4,
	Q3D_I3DL2_LIVINGROOM = 5,
	Q3D_I3DL2_STONEROOM = 6,
	Q3D_I3DL2_AUDITORIUM = 7,
	Q3D_I3DL2_CONCERTHALL = 8,
	Q3D_I3DL2_CAVE = 9,
	Q3D_I3DL2_ARENA = 10,
	Q3D_I3DL2_HANGAR = 11,
	Q3D_I3DL2_CARPETEDHALLWAY = 12,
	Q3D_I3DL2_HALLWAY = 13,
	Q3D_I3DL2_STONECORRIDOR = 14,
	Q3D_I3DL2_ALLEY = 15,
	Q3D_I3DL2_FOREST = 16,
	Q3D_I3DL2_CITY = 17,
	Q3D_I3DL2_MOUNTAINS = 18,
	Q3D_I3DL2_QUARRY = 19,
	Q3D_I3DL2_PLAIN = 20,
	Q3D_I3DL2_PARKINGLOT = 21,
	Q3D_I3DL2_SEWERPIPE = 22,
	Q3D_I3DL2_UNDERWATER = 23
} Q3D_I3DL2_ROOMTYPE;

/*
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_EnableSynthReverb(Q3D_Env, Q3D_BOOL enabled);

/*
 * The room parameter is either Q3D_MIDI_ROOMTYPE or Q3D_I3DL2_ROOMTYPE.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetSynthReverbRoom(Q3D_Env, Q3D_REVERB_TYPE type, int room);

/*
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetSynthReverbVolume(Q3D_Env, int volume);

/*
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_EnableSynthChorus(Q3D_Env, Q3D_BOOL enabled);

/*
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetSynthChorusType(Q3D_Env, int type);

/**
 * Create a synthesizer player.  Multiple players may be created.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_CreateSynthPlayer(Q3D_Env, Q3D_IPlayControl** synth, const Q3D_HostBlock* soundData);

/**
 * Attach a player to be played.  The priority indicates relative priority for the voice stealing algorithm.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_AttachSynthPlayer(Q3D_Env, Q3D_IPlayControl*, int priority);

/**
 * Detach the player.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_DetachSynthPlayer(Q3D_Env, Q3D_IPlayControl*);

typedef void (Q3D_CALLBACK* Q3D_VibrateCallback)(void* params, Q3D_BOOL);
typedef void (Q3D_CALLBACK* Q3D_LEDCallback)(void* params, Q3D_BOOL);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetSynthVibrateCallback(Q3D_Env env, Q3D_VibrateCallback callback, void* params);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetSynthLEDCallback(Q3D_Env env, Q3D_LEDCallback callback, void* params);

_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetNoteLimiting(Q3D_Env, int maxNotesPerBlock, int maxDeferredNotesPerBlock);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_DisableNoteLimiting(Q3D_Env);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_EnableSynthPreroll(Q3D_Env, Q3D_BOOL enabled);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetExSynthSpread(Q3D_Env env, int spread);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetSynthVoices(Q3D_Env, int* voices);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_GetSynthWaves(Q3D_Env, int* waves);
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_SetSynthTextDisplay(Q3D_Env, Q3D_ISynthTextDisplay*);

/**
 * Reset the synth.
 */
_Q3DIMP Q3D_ERROR Q3D_API Q3DE_ResetSynth(Q3D_Env env);



/*************************************************************
* Host Storage C Interface
*************************************************************/
typedef void (Q3D_CALLBACK* Func_HS_ReadPacked)(void* chs_data, void* buffer, long position, int size);
typedef void (Q3D_CALLBACK* Func_HS_ReadUnpacked)(void* chs_data, unsigned char* buffer, long position, int bytes);
typedef void (Q3D_CALLBACK* Func_HS_Convert8to16)(void* chs_data, short* buffer, long position, int bytes);
typedef void (Q3D_CALLBACK* Func_HS_SetPage)(void* chs_data, unsigned char page);
typedef unsigned char (Q3D_CALLBACK* Func_HS_GetPage)(void* chs_data);


/** 
* Create an HostStorage object. The implementation is provided by the integrator/end-user. Several C
* functions are required to provide the functionality of the object. Typedefs for the required function
* pointers are provided above.
* @param chs_data pointer to user-defined structure or memory, which will be passed to each C function when called
* @param ReadPacked function pointer to ReadPacked C function implementation (non-null)
* @param ReadUnpacked function pointer (non-null)
* @param Convert8to16 function pointer (non-null)
* @param SetPage function pointer (non-null)
* @param GetPage function pointer (non-null)
* @return pointer to Q3D_IHostStorage handle
*/
_Q3DIMP Q3D_IHostStorage *Q3D_API  Q3DE_CreateHostStorage( void* chs_data,
													   Func_HS_ReadPacked ReadPacked,
													   Func_HS_ReadUnpacked ReadUnpacked,
													   Func_HS_Convert8to16 Convert8to16,
													   Func_HS_SetPage SetPage,
													   Func_HS_GetPage GetPage);

_Q3DIMP void Q3D_API  Q3DE_DeleteHostStorage( Q3D_IHostStorage *handle );




/*************************************************************
* Event Trigger C callback
*************************************************************/
typedef void (Q3D_CALLBACK* Func_ET_EventTriggered)(void* et_data );

/*************************************************************
* Create an EventTrigger object. The implementation is provided by the integrator/end-user. Typedefs for
* the required function pointers are provided above.
*
* @param et_data pointer to user-defined structure or memory, which will be passed to the callback
* @param EventTriggered the call back function (non-null)
* @return pointer to Q3D_IEventTrigger handle
*************************************************************/
_Q3DIMP Q3D_IEventTrigger *Q3D_API  Q3DE_CreateEventTrigger( void* inData, Func_ET_EventTriggered inEvent );
_Q3DIMP void Q3D_API  Q3DE_DeleteEventTrigger( Q3D_IEventTrigger *handle );






/*************************************************************
* Synth Text Display C callback
*************************************************************/
typedef void (Q3D_CALLBACK* Func_STD_DisplayCopyright)( void* std_data,	
													    unsigned int inTextLength,
														const char *inText );
typedef void (Q3D_CALLBACK* Func_STD_DisplayText)( void* std_data,	
												   unsigned int inTextLength,
												   const char *inText );
typedef void (Q3D_CALLBACK* Func_STD_DisplayLyric)( void* std_data,	
												    unsigned int inTextLength,
												    const char *inText );

/*************************************************************
* Create an SynthTextDisplay object. The implementation is provided by the integrator/end-user. 
* Typedefs for the required function pointers are provided above.
*
* @param et_data pointer to user-defined structure or memory, which will be passed to the callback
* @param EventTriggered the call back function (non-null)
* @return pointer to Q3D_ISynthTextDisplay handle
*************************************************************/
_Q3DIMP Q3D_ISynthTextDisplay *Q3D_API  Q3DE_CreateSynthTextDisplay( void* inData, 
														 Func_STD_DisplayCopyright inCopyright,
														 Func_STD_DisplayText inText,
														 Func_STD_DisplayLyric inLyric );
_Q3DIMP void Q3D_API  Q3DE_DeleteSynthTextDisplay( Q3D_ISynthTextDisplay *handle );


/*************************************************************
* Q3D_IPlayControl C Interfaces 
* - use Q3DE_CreateSynthPlayer() to get the handle
*************************************************************/
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_PC_AddRef( Q3D_IPlayControl *inHandle );
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_PC_Release( Q3D_IPlayControl *inHandle );
_Q3DIMP Q3D_BOOL Q3D_API Q3DC_PC_SetPosition( Q3D_IPlayControl* inHandle, long inTenthsMs );
_Q3DIMP long Q3D_API Q3DC_PC_GetPosition( Q3D_IPlayControl* inHandle );
_Q3DIMP long Q3D_API Q3DC_PC_GetDuration( Q3D_IPlayControl* inHandle );
_Q3DIMP void Q3D_API Q3DC_PC_SetVolume( Q3D_IPlayControl* inHandle, int inVolume );
_Q3DIMP int Q3D_API Q3DC_PC_GetVolume( Q3D_IPlayControl* inHandle );
_Q3DIMP void Q3D_API Q3DC_PC_SetLoops( Q3D_IPlayControl* inHandle, int inLoops );
_Q3DIMP void Q3D_API Q3DC_PC_Play( Q3D_IPlayControl* inHandle, Q3D_BOOL inPlay );
_Q3DIMP Q3D_BOOL Q3D_API Q3DC_PC_IsPlaying( Q3D_IPlayControl* inHandle );
_Q3DIMP Q3D_BOOL Q3D_API Q3DC_PC_IsDone( Q3D_IPlayControl* inHandle );
_Q3DIMP void Q3D_API Q3DC_PC_Flush( Q3D_IPlayControl* inHandle );
_Q3DIMP void Q3D_API Q3DC_PC_ResetAll( Q3D_IPlayControl* inHandle );
_Q3DIMP Q3D_ISynthPerformance * Q3D_API Q3DC_PC_GetSynthPerformance( Q3D_IPlayControl *inHandle );
_Q3DIMP Q3D_IMidiControl * Q3D_API Q3DC_PC_GetMidiControl( Q3D_IPlayControl *inHandle );
_Q3DIMP Q3D_IPitchControl * Q3D_API Q3DC_PC_GetPitchControl( Q3D_IPlayControl *inHandle );
_Q3DIMP Q3D_IRateControl * Q3D_API Q3DC_PC_GetRateControl( Q3D_IPlayControl *inHandle );
_Q3DIMP Q3D_ITempoControl * Q3D_API Q3DC_PC_GetTempoControl( Q3D_IPlayControl *inHandle );
_Q3DIMP Q3D_IVolumeControl * Q3D_API Q3DC_PC_GetVolumeControl( Q3D_IPlayControl *inHandle );

/*************************************************************
* Q3D_ISynthPerformance C Interfaces
* use Q3DC_PC_GetSynthPerformance(...) to get the handle
*************************************************************/
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_SP_AddRef( Q3D_ISynthPerformance *inHandle );
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_SP_Release( Q3D_ISynthPerformance *inHandle );
_Q3DIMP void Q3D_API Q3DC_SP_SetVelocityMapping( Q3D_ISynthPerformance *, Q3D_VELOCITYMAPPING inMappingType );
_Q3DIMP void Q3D_API Q3DC_SP_EnabledChannel( Q3D_ISynthPerformance *, int inChannel,
											Q3D_BOOL inEnabled);
_Q3DIMP void Q3D_API Q3DC_SP_WriteEvent( Q3D_ISynthPerformance *, unsigned long inTenthsMs, 
										unsigned char inStatus, const unsigned char * inData, 
										int inBytes );
_Q3DIMP void Q3D_API Q3DC_SP_GetVoiceCounts( Q3D_ISynthPerformance *, int inVoices[16] );
_Q3DIMP void Q3D_API Q3DC_SP_SetDoneCallback( Q3D_ISynthPerformance *, Q3D_IEventTrigger * );


/*************************************************************
* Q3D_IMidiControl C interface for JSR135
* use Q3DC_PC_GetMidiControl(...) to get the handle
*************************************************************/
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_MC_AddRef( Q3D_IMidiControl *inHandle );
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_MC_Release( Q3D_IMidiControl *inHandle );
_Q3DIMP JSR135ErrorCode Q3D_API Q3DC_MC_GetBankList( Q3D_IMidiControl *inHandle, Q3D_BOOL inCustom, short *outBanklist, int *inoutNumBanks );
_Q3DIMP JSR135ErrorCode Q3D_API Q3DC_MC_GetChannelVolume( Q3D_IMidiControl *inHandle, int inChannel, int *outVolume );
_Q3DIMP JSR135ErrorCode Q3D_API Q3DC_MC_GetKeyName( Q3D_IMidiControl *inHandle, int inBank, int inProgram, int inKey, char *outName, int inNameLength );
_Q3DIMP JSR135ErrorCode Q3D_API Q3DC_MC_GetProgram( Q3D_IMidiControl *inHandle, int inChannel, int *outBank, int *outProgram );
_Q3DIMP JSR135ErrorCode Q3D_API Q3DC_MC_GetProgramList( Q3D_IMidiControl *inHandle, int inBank, char *outProgramList, int *outNumPrograms );
_Q3DIMP JSR135ErrorCode Q3D_API Q3DC_MC_GetProgramName( Q3D_IMidiControl *inHandle, int inBank, int inProgram, char *outName, int inNameLength );
_Q3DIMP Q3D_BOOL Q3D_API Q3DC_MC_IsBankQuerySupported( Q3D_IMidiControl *inHandle );
_Q3DIMP JSR135ErrorCode Q3D_API Q3DC_MC_LongMidiEvent( Q3D_IMidiControl *inHandle, unsigned char *inData, int inOffset, int inLength, int *outNumBytesUsed );
_Q3DIMP JSR135ErrorCode Q3D_API Q3DC_MC_SetChannelVolume( Q3D_IMidiControl *inHandle, int inChannel, int inVolume );
_Q3DIMP JSR135ErrorCode Q3D_API Q3DC_MC_SetProgram( Q3D_IMidiControl *inHandle, int inChannel, int inBank, int inProgram );
_Q3DIMP JSR135ErrorCode Q3D_API Q3DC_MC_ShortMidiEvent( Q3D_IMidiControl *inHandle, int inType, int inData1, int inData2 );

/*************************************************************
* Q3D_IPitchControl C interface for JSR135
* use Q3DC_PC_GetPitchControl(...) to get the handle
*************************************************************/
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_P_AddRef( Q3D_IPitchControl *inHandle );
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_P_Release( Q3D_IPitchControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_P_GetMaxPitch( Q3D_IPitchControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_P_GetMinPitch( Q3D_IPitchControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_P_GetPitch( Q3D_IPitchControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_P_SetPitch( Q3D_IPitchControl *inHandle, int inMilliSemiTones );


/*************************************************************
* Q3D_IRateControl C interface for JSR135
* use Q3DC_PC_GetRateControl(...) to get the handle
*************************************************************/
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_RC_AddRef( Q3D_IRateControl *inHandle );
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_RC_Release( Q3D_IRateControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_RC_GetMaxRate( Q3D_IRateControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_RC_GetMinRate( Q3D_IRateControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_RC_GetRate( Q3D_IRateControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_RC_SetRate( Q3D_IRateControl *inHandle, int inMilliRate );

/*************************************************************
* Q3D_ITempoControl C interface for JSR135
* use Q3DC_PC_TempControl(...) to get the handle
*************************************************************/
_Q3DIMP int Q3D_API Q3DC_TC_GetTempo( Q3D_ITempoControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_TC_SetTempo( Q3D_ITempoControl *inHandle, int inMilliTempo );


/*************************************************************
* Q3D_IVolumeControl C interface for JSR135
* use Q3DC_PC_GetVolumeControl(...) to get the handle
*************************************************************/
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_VC_AddRef( Q3D_IVolumeControl *inHandle );
_Q3DIMP Q3D_REFCOUNT Q3D_API Q3DC_VC_Release( Q3D_IVolumeControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_VC_GetLevel( Q3D_IVolumeControl *inHandle );
_Q3DIMP Q3D_BOOL Q3D_API Q3DC_VC_IsMuted( Q3D_IVolumeControl *inHandle );
_Q3DIMP int Q3D_API Q3DC_VC_SetLevel( Q3D_IVolumeControl *inHandle, int inLevel );
_Q3DIMP void Q3D_API Q3DC_VC_SetMute( Q3D_IVolumeControl *inHandle, Q3D_BOOL inIsMute );

#ifdef __cplusplus
}
#endif

#endif
